﻿#pragma once
#if defined(_MSVC_LANG)
    #define _CRT_SECURE_NO_WARNINGS
#endif
#include "CFileBase.h"
#include <iostream>
#include <vector>
#include <cerrno>
#include <sstream>

// Additional headers for cross-platform getcwd
#if defined(_WIN32) || defined(_WIN64)
    #include <io.h>
    #include <direct.h> // _getcwd
    #define getcwd _getcwd
#else
    #include <unistd.h> // getcwd
#endif

// IMPORTANT: use large-file-aware fseek/ftello wrappers
// Many platforms provide 64-bit file positioning APIs:
//  - MSVC: _fseeki64 / _ftelli64 (use with FILE*)
//  - POSIX (Linux, macOS, clang/gcc): fseeko / ftello (use off_t)
// We provide small wrapper functions so the rest of the code uses a
// consistent int64_t interface and can handle files > 2GB/4GB.
//
// This implementation performs compile-time detection with reasonable
// fallbacks for older platforms. If neither 64-bit API is available
// we fall back to fseek/ftell (32-bit) and record a debug message —
// this preserves functionality on legacy systems but may not support
// very large files correctly.

static inline int file_seek64(FILE* f, int64_t offset, int origin)
{
    if (!f)
        return -1;
#if defined(_WIN32) || defined(_WIN64)
    // MSVC and MinGW provide _fseeki64
    return _fseeki64(f, (long long)offset, origin);
#elif defined(__APPLE__) || defined(__linux__) || defined(__unix__) || defined(_POSIX_VERSION) || defined(_LARGEFILE64_SOURCE)
    // On POSIX-like systems prefer fseeko which uses off_t (typically 64-bit when
    // _FILE_OFFSET_BITS=64 is enabled). Many modern systems already have 64-bit off_t.
    return fseeko(f, (off_t)offset, origin);
#else
    // Fallback: use fseek (may be 32-bit on old systems). Record debug info in case
    // callers are trying to use >2GB offsets on a platform that doesn't support it.
    set_debug_msg("CFileBase debug info: fseeko/\_fseeki64 not available, falling back to fseek (limited to 32-bit offsets).");
    return fseek(f, (long)offset, origin);
#endif
}

static inline int64_t file_tell64(FILE* f)
{
    if (!f)
        return -1;
#if defined(_WIN32) || defined(_WIN64)
    long long r = _ftelli64(f);
    return (int64_t)r;
#elif defined(__APPLE__) || defined(__linux__) || defined(__unix__) || defined(_POSIX_VERSION) || defined(_LARGEFILE64_SOURCE)
    off_t r = ftello(f);
    return (int64_t)r;
#else
    set_debug_msg("CFileBase debug info: ftello/\_ftelli64 not available, falling back to ftell (limited to 32-bit offsets).");
    long r = ftell(f);
    return (int64_t)r;
#endif
}

// Helper: duplicate C string in a portable way (avoid strdup dependency)
// 中文注释：跨平台的字符串复制函数，避免直接使用 strdup 带来的可移植性问题
// 参数：s - 要复制的源字符串，可以为 nullptr
// 返回值：新分配的字符串指针，需要调用者负责释放，失败返回 nullptr
static char* duplicate_cstr(const char* s) {
    if (!s)
        return nullptr;
    size_t len = std::strlen(s);
    char* p = (char*)std::malloc(len + 1);
    if (!p)
        return nullptr;
    std::memcpy(p, s, len + 1);
    return p;
}

// Debug message returned by get_debug_mag()
// 重构提示：使用 std::string 管理调试信息，便于后续扩展（例如格式化、线程本地化等）
static std::string g_debug_msg = "CFileBase debug info: No error."; // 默认没错误

// Helper to set debug message in one place. 如果需要，可以在这里添加时间戳或线程信息
static inline void set_debug_msg(const char* msg) {
    if (msg)
        g_debug_msg.assign(msg);
    else
        g_debug_msg.clear();
}

static inline void set_debug_msg_fmt(const std::string& msg)
{
    g_debug_msg = msg;
}

// Default constructor
// 功能：创建CFileBase对象，自动获取当前工作目录
// 注意：构造后文件处于关闭状态，需要调用 open_file 打开文件
CFileBase::CFileBase()
    : file_(nullptr)
    , mode_(nullptr)
    , cwd_(nullptr)
    , file_content_(nullptr)
    , file_name_(nullptr)
    , pos_(0)
    , is_open_(false)
{
    // capture current working directory on construction
    // 在构造时获取当前工作目录
    char buf[2048] = { 0 };
    if (getcwd(buf, sizeof(buf))) {
        cwd_ = duplicate_cstr(buf);
    }
    else {
        cwd_ = duplicate_cstr(".");
    }
}

// Construct from C string filename
CFileBase::CFileBase(const char* sz_file_name)
    : CFileBase() // call default constructor to init cwd
{
    if (sz_file_name) {
        file_name_ = duplicate_cstr(sz_file_name);
    }
}

// Construct from std::string filename
CFileBase::CFileBase(const std::string& str_file_name)
    : CFileBase(str_file_name.c_str())
{
}

// Copy constructor (performs deep copy for internal strings but does not duplicate open FILE*)
CFileBase::CFileBase(const CFileBase& file)
    : file_(nullptr)
    , mode_(file.mode_)
    , cwd_(nullptr)
    , file_content_(nullptr)
    , file_name_(nullptr)
    , pos_(file.pos_)
    , is_open_(false)
{
    cwd_ = duplicate_cstr(file.cwd_);
    file_name_ = duplicate_cstr(file.file_name_);
}

// Move constructor
CFileBase::CFileBase(CFileBase&& file) noexcept
    : file_(file.file_)
    , mode_(file.mode_)
    , cwd_(file.cwd_)
    , file_content_(file.file_content_)
    , file_name_(file.file_name_)
    , pos_(file.pos_)
    , is_open_(file.is_open_)
{
    // Null out source so it won't free resources
    file.file_ = nullptr;
    file.cwd_ = nullptr;
    file.file_content_ = nullptr;
    file.file_name_ = nullptr;
    file.is_open_ = false;
}

// Copy assignment
CFileBase& CFileBase::operator=(const CFileBase& file)
{
    if (this == &file)
        return *this;
    // close current file if open
    close_file();
    // free existing strings
    if (cwd_)
        { std::free((void*)cwd_); cwd_ = nullptr; }
    if (file_content_)
        { std::free((void*)file_content_); file_content_ = nullptr; }
    if (file_name_)
        { std::free((void*)file_name_); file_name_ = nullptr; }

    mode_ = file.mode_;
    pos_ = file.pos_;
    is_open_ = false;
    cwd_ = duplicate_cstr(file.cwd_);
    file_name_ = duplicate_cstr(file.file_name_);
    return *this;
}

// Move assignment
CFileBase& CFileBase::operator=(CFileBase&& file) noexcept
{
    if (this == &file)
        return *this;
    close_file();
    if (cwd_)
        { std::free((void*)cwd_); cwd_ = nullptr; }
    if (file_content_)
        { std::free((void*)file_content_); file_content_ = nullptr; }
    if (file_name_)
        { std::free((void*)file_name_); file_name_ = nullptr; }

    file_ = file.file_;
    mode_ = file.mode_;
    cwd_ = file.cwd_;
    file_content_ = file.file_content_;
    file_name_ = file.file_name_;
    pos_ = file.pos_;
    is_open_ = file.is_open_;

    file.file_ = nullptr;
    file.cwd_ = nullptr;
    file.file_content_ = nullptr;
    file.file_name_ = nullptr;
    file.is_open_ = false;
    return *this;
}

// Destructor: close file and free allocated buffers
CFileBase::~CFileBase()
{
    close_file();
    if (cwd_)
        { std::free((void*)cwd_); cwd_ = nullptr; }
    if (file_content_)
        { std::free((void*)file_content_); file_content_ = nullptr; }
    if (file_name_)
        { std::free((void*)file_name_); file_name_ = nullptr; }
}

// Open file using C stdio. mode follows fopen conventions. If mode is not provided, default to "r+" (read/write).
// 中文注释：打开文件方法
// 功能：使用C标准库打开文件，支持多种打开模式
// 参数：
//   sz_file_name - 要打开的文件路径，不能为 nullptr
//   mode - 文件打开模式，遵循 fopen 规范，如"r"(读)、"w"(写)等
// 返回值：打开成功返回 true，失败返回 false
// 注意：
//   1. 如果以读模式打开不存在的文件，会自动创建该文件
//   2. 打开新文件前会自动关闭已打开的文件
//   3. 在文本模式下，由于 CRLF 翻译，文件中某些 '\n' 实际上占 2 个字节，这会使得从 pos 实际能读到的字节数与 ftell 报告的不同；把文件以二进制打开后不会发生翻译
//   4. 文本模式的换行转换和文本模式下定位/计数的不可靠性，造成了读取长度不一致和“乱码/残缺”的现象。
bool CFileBase::open_file(const char* sz_file_name, const char* mode)
{
    if (!sz_file_name) {
        set_debug_msg("CFileBase debug info: Null file name.");
        return false;
    }
    // close existing file first
    // 中文注释：首先关闭已打开的文件
    close_file();

    // store mode (keep original pointer, but we'll open with a binary-aware mode if needed)
    // 中文注释：保存打开模式
    mode_ = mode;

    // copy file name
    // 中文注释：复制文件名
    if (file_name_)
        { std::free((void*)file_name_); file_name_ = nullptr; }
    file_name_ = duplicate_cstr(sz_file_name);

    // Prepare fopen mode string. On Windows/text-mode, writing '\n' will be translated to "\r\n"
    // and reading will translate back. This makes byte offsets and sizes inconsistent when the
    // program expects exact byte counts (fseek/ftell/fread). To avoid CRLF translation and
    // make file operations byte-accurate, we force binary mode for fopen on platforms where
    // text-mode does translation (Windows). If the user provided a mode that already contains
    // 'b', we use it as-is.
    const char* fopen_mode = mode;
    char* tmp_mode = nullptr;
#if defined(_WIN32) || defined(_WIN64)
    if (!std::strchr(mode, 'b')) {
        // append 'b' to the provided mode string, e.g. "w+" -> "w+b"
        size_t mlen = std::strlen(mode);
        tmp_mode = (char*)std::malloc(mlen + 2); // +1 for 'b', +1 for '\0'
        if (!tmp_mode) {
            set_debug_msg("CFileBase debug info: Failed to allocate memory for fopen mode.");
            return false;
        }
        std::memcpy(tmp_mode, mode, mlen);
        tmp_mode[mlen] = 'b';
        tmp_mode[mlen + 1] = '\0';
        fopen_mode = tmp_mode;
    }
#endif

    // Try to open. If opening for reading/writing exclusively fails because file doesn't exist, create it.
    // 中文注释：尝试打开文件。如果以独占读写模式打开失败(文件不存在)，则创建文件
    file_ = std::fopen(sz_file_name, fopen_mode);
    if (!file_ && (std::strcmp(mode, "r+") == 0 || std::strcmp(mode, "r") == 0)) {
        // attempt to create file and reopen
        // 中文注释：尝试创建文件并重新打开
        // Use binary create mode as well to be consistent
        const char* create_mode = "w";
//#if defined(_WIN32) || defined(_WIN64)
        char* tmp_create = (char*)std::malloc(3);
        if (!tmp_create) {
            if (tmp_mode) std::free(tmp_mode);
            set_debug_msg("CFileBase debug info: Failed to allocate memory for create mode.");
            return false;
        }
        std::memcpy(tmp_create, "w", 1);
        tmp_create[1] = 'b';
        tmp_create[2] = '\0';
        create_mode = tmp_create;
        FILE* tmp = std::fopen(sz_file_name, create_mode);
        if (tmp) std::fclose(tmp);
        // reopen using fopen_mode (which may have 'b')
        file_ = std::fopen(sz_file_name, fopen_mode);
        std::free(tmp_create);
    } else {
        // not the 'r' case: if we used tmp_mode, still try to open and handle
        if (!file_) {
            // try once without special create step
            file_ = std::fopen(sz_file_name, fopen_mode);
        }
    }

    if (tmp_mode) {
        std::free(tmp_mode);
        tmp_mode = nullptr;
    }

    if (!file_) {
        // failed to open file
        set_debug_msg("CFileBase debug info: Failed to open file.");
        is_open_ = false;
        return false;
    }

    is_open_ = true;
    // set position to start
    // 中文注释：将文件指针设置到起始位置
    file_seek64(file_, 0, SEEK_SET);
    pos_ = 0;
    set_debug_msg("CFileBase debug info: No error.");
    return true;
}

// Close file and update state
// 中文注释：关闭文件方法
// 功能：关闭当前打开的文件并更新对象状态
// 返回值：关闭成功返回 true，失败返回 false
// 注意：
//   1. 如果文件未打开，直接返回 true
//   2. 关闭前会自动刷新缓冲区
// 额外改进：关闭时释放 file_content_ 和 file_name_（释放这些缓存可以避免长期占用内存；如果希望在 close 后保留 file_name_，可去掉释放 file_name_ 的语句）
bool CFileBase::close_file()
{
    bool close_success = true;
    if (file_) {
        std::fflush(file_);
        int close_result = std::fclose(file_);
        file_ = nullptr;
        is_open_ = false;
        close_success = (close_result == 0);
    }
    else {
        is_open_ = false;
    }

    // free any cached content buffer
    if (file_content_) {
        std::free((void*)file_content_);
        file_content_ = nullptr;
    }

    // 这里选择释放 file_name_：如果调用者希望在 close 之后仍能访问文件名，则不要释放。
    // 在本实现中，为了避免长时间持有内存，close_file 会释放 file_name_，open_file 会在下一次打开时重新分配。
    if (file_name_) {
        std::free((void*)file_name_);
        file_name_ = nullptr;
    }

    if (close_success)
        set_debug_msg("CFileBase debug info: No error.");
    else
        set_debug_msg("CFileBase debug info: Failed to close file.");
    return close_success;
}

// Return current working directory string pointer (owned by object, caller must not free)
const char* CFileBase::get_cwd()
{
    return cwd_;
}

// Return file name (not including path). If file_name_ contains path separators, extract base name.
const char* CFileBase::get_file_name() const
{
    if (!file_name_) {
        set_debug_msg("CFileBase debug info: Null file name.");
        return nullptr;
    }
    const char* p = file_name_;
    const char* last_sep = p;
    for (; *p; ++p) {
        if (*p == '/' || *p == '\\')
            last_sep = p + 1;
    }
    set_debug_msg("CFileBase debug info: No error.");
    return last_sep;
}

// Move file pointer to absolute position pos
inline void CFileBase::seek_to(int64_t pos)
{
    if (!file_) {
        set_debug_msg("CFileBase debug info: File not open.");
        return;
    }
    // Use the 64-bit wrapper to support large files (>2GB)
    file_seek64(file_, (int64_t)pos, SEEK_SET);
    pos_ = file_tell64(file_);
    set_debug_msg("CFileBase debug info: No error.");
}

void CFileBase::seek_start()
{
    if (!file_) {
        set_debug_msg("CFileBase debug info: File not open.");
        return;
    }
    file_seek64(file_, 0, SEEK_SET);
    pos_ = 0;
    set_debug_msg("CFileBase debug info: No error.");
}

void CFileBase::seek_end()
{
    if (!file_) {
        set_debug_msg("CFileBase debug info: File not open.");
        return;
    }
    file_seek64(file_, 0, SEEK_END);
    pos_ = (uint64_t)file_tell64(file_);
    set_debug_msg("CFileBase debug info: No error.");
}

int64_t CFileBase::tell_pos()
{
    if (!file_) {
        set_debug_msg("CFileBase debug info: File not open.");
        return 0;
    }
    pos_ = file_tell64(file_);
    set_debug_msg("CFileBase debug info: No error.");
    return pos_;
}

// Read a single line from current position into internal file_content_ buffer (NUL-terminated). Uses fgets semantics.
// 中文注释：读取一行内容到内部缓冲区
// 功能：从当前位置读取一行内容到 file_content_ 缓冲区
// 注意：
//   1. 读取内容包括换行符
//   2. 缓冲区以 NULL 结尾
//   3. 会自动释放之前的内容
//   4. 文件指针会移动到下一行开始位置
void CFileBase::read_line()
{
    if (!file_) {
        set_debug_msg("CFileBase debug info: File not open.");
        return;
    }
    // We'll read one line of arbitrary length by reading in chunks
    // 中文注释：通过分块读取方式读取任意长度的单行内容
    std::vector<char> buf;
    buf.reserve(256);
    int ch;
    while ((ch = std::fgetc(file_)) != EOF) {
        buf.push_back((char)ch);
        if (ch == '\n')
            break;
    }
    buf.push_back('\0');
    // free previous content
    // 中文注释：释放之前的内容
    if (file_content_) {
        std::free((void*)file_content_);
        file_content_ = nullptr;
    }
    file_content_ = duplicate_cstr(buf.data());
    pos_ = tell_pos();
    set_debug_msg("CFileBase debug info: No error.");
}

// 中文注释：读取文件全部内容到内部缓冲区
// 功能：从当前位置读取文件剩余全部内容到 file_content_ 缓冲区
// 注意：
//   1. 缓冲区以 NULL 结尾
//   2. 会自动释放之前的内容
//   3. 文件指针会移动到文件末尾
void CFileBase::read_all()
{
    if (!file_) {
        set_debug_msg("CFileBase debug info: File not open.");
        return;
    }
    // determine remaining size
    // 中文注释：确定剩余文件大小
    int64_t cur = file_tell64(file_);
    file_seek64(file_, 0, SEEK_END);
    int64_t end = file_tell64(file_);
    int64_t remain = end - cur;
    file_seek64(file_, cur, SEEK_SET);

    if (remain <= 0) {
        if (file_content_) {
            std::free((void*)file_content_);
            file_content_ = nullptr;
        }
        file_content_ = duplicate_cstr("");
        set_debug_msg("CFileBase debug info: No read data.");
        return;
    }

    // allocate using size_t but check that remain fits
    if ((uint64_t)remain > (uint64_t)SIZE_MAX - 1) {
        set_debug_msg("CFileBase debug info: File too large to read into memory.");
        return;
    }

    char* buf = (char*)std::malloc((size_t)remain + 1);
    if (!buf) {
        set_debug_msg("CFileBase debug info: Failed to allocate buffer.");
        return;
    }
    size_t bytes_read = std::fread(buf, 1, (size_t)remain, file_);
    buf[bytes_read] = '\0';

    if (file_content_) {
        std::free((void*)file_content_);
        file_content_ = nullptr;
    }
    file_content_ = buf; // take ownership
    pos_ = tell_pos();
    // Provide more detailed debug info including number of bytes read
    {
        std::ostringstream oss;
        oss << "CFileBase debug info: Read " << bytes_read << " bytes into internal buffer.";
        set_debug_msg_fmt(oss.str());
    }
}

void CFileBase::read_size(size_t size)
{
    if (!file_)
        return;
    if (size == 0) {
        if (file_content_) {
            std::free((void*)file_content_);
            file_content_ = nullptr;
        }
        file_content_ = duplicate_cstr("");
        return;
    }
    char* buf = (char*)std::malloc(size + 1);
    if (!buf) {
        set_debug_msg("CFileBase debug info: Failed to allocate buffer.");
        return;
    }
    size_t bytes_read = std::fread(buf, 1, size, file_);
    buf[bytes_read] = '\0';
    if (file_content_) {
        std::free((void*)file_content_);
        file_content_ = nullptr;
    }
    file_content_ = buf;
    pos_ = tell_pos();
    {
        std::ostringstream oss;
        oss << "CFileBase debug info: Read " << bytes_read << " bytes into internal buffer (read_size).";
        set_debug_msg_fmt(oss.str());
    }
}

int64_t CFileBase::read_line(std::string& str_line)
{
    if (!file_) {
        set_debug_msg("CFileBase debug info: File not open.");
        return 0;
    }
    std::vector<char> buf;
    // 这里的 reserve 大小是 256，即一次预分配内存，如果一行的字符数超过256个，std::vector<char> 会自动扩展其容量来容纳更多的字符。因此，超出部分也会被读取。
    buf.reserve(256);
    int ch;
    int64_t line_len = 0;
    while ((ch = std::fgetc(file_)) != EOF) {
        buf.push_back((char)ch);
        ++line_len;
        if (ch == '\n')
            break;
    }
    if (buf.empty()) {
        set_debug_msg("CFileBase debug info: No data read.");
        return 0; // no data read
    }
    str_line.assign(buf.data(), buf.size());
    pos_ = tell_pos();
    set_debug_msg("CFileBase debug info: No error.");
    return line_len;
}

int64_t CFileBase::read_all(std::string& str_all)
{
    if (!file_) {
        set_debug_msg("CFileBase debug info: File not open.");
        return 0;
    }
    int64_t cur = file_tell64(file_);
    file_seek64(file_, 0, SEEK_END);
    int64_t end = file_tell64(file_);
    int64_t remain = end - cur;
    file_seek64(file_, cur, SEEK_SET);
    if (remain <= 0) {
        str_all.clear();
        set_debug_msg("CFileBase debug info: No read data.");
        return 0;
    }
    if ((uint64_t)remain > (uint64_t)SIZE_MAX) {
        set_debug_msg("CFileBase debug info: File too large to read into memory.");
        return 0;
    }
    // Use std::string resize + fread directly into string buffer to avoid temporary issues
    str_all.clear();
    str_all.resize((size_t)remain);
    size_t bytes_read = std::fread(&str_all[0], 1, (size_t)remain, file_);
    if (bytes_read < (size_t)remain) {
        // shrink to actual read
        str_all.resize(bytes_read);
    }
    pos_ = tell_pos();
    {
        std::ostringstream oss;
        oss << "CFileBase debug info: Read " << bytes_read << " bytes into std::string.";
        set_debug_msg_fmt(oss.str());
    }
    return bytes_read;
}

size_t CFileBase::read_size(size_t size, std::string& str_content)
{
    if (!file_) {
        set_debug_msg("CFileBase debug info: File not open.");
        return 0;
    }
    if (size == 0) {
        str_content.clear();
        set_debug_msg("CFileBase debug info: No read data.");
        return 0;
    }
    str_content.clear();
    str_content.resize(size);
    size_t bytes_read = std::fread(&str_content[0], 1, size, file_);
    if (bytes_read < size)
        str_content.resize(bytes_read);
    pos_ = tell_pos();
    set_debug_msg("CFileBase debug info: No error.");
    return bytes_read;
}

// 中文注释：在文件末尾写入内容
// 功能：在文件末尾追加写入指定字符串内容
// 参数：
//   str_end - 要写入的字符串内容，不能为 nullptr
// 返回值：写入成功返回 true，失败返回 false
// 注意：
//   1. 写入前会自动将文件指针移动到文件末尾
//   2. 写入后会自动刷新缓冲区
size_t CFileBase::write_end(const char* str_end)
{
    if (!file_ || !str_end) {
        set_debug_msg("CFileBase debug info: Invalid arguments or file not open.");
        return 0;
    }
    if (mode_ == "r") {
        set_debug_msg("CFileBase debug info: File not open for writing.");
        return 0;
    }
    file_seek64(file_, 0, SEEK_END);
    size_t len = std::strlen(str_end);
    size_t bytes_written = std::fwrite(str_end, 1, len, file_);
    std::fflush(file_);
    pos_ = tell_pos();
    bool ret = (bytes_written == len);
    if (ret)
        set_debug_msg("CFileBase debug info: No error.");
    else {
        std::ostringstream oss;
        oss << "CFileBase debug info: Failed to write all data. wrote=" << bytes_written << " expected=" << len;
        set_debug_msg_fmt(oss.str());
    }
    return bytes_written;
}

// write content at given position. If is_insert is true, insert content shifting the rest of file.
// 中文注释：在指定位置写入内容
// 功能：在文件指定位置写入内容，可选择插入或覆盖模式
// 参数：
//   str_content - 要写入的字符串内容，不能为 nullptr
//   pos - 要写入的位置
//   is_insert - 是否为插入模式(true=插入，false=覆盖)
// 返回值：写入成功返回 true，失败返回 false
// 注意：
//   1. 插入模式会保存当前位置后的内容，写入新内容后再追加保存的内容
//   2. 写入后会自动刷新缓冲区
int64_t CFileBase::write_pos(const char* str_content, int64_t pos, bool is_insert)
{
    if (!file_ || !str_content) {
        set_debug_msg("CFileBase debug info: Invalid arguments or file not open.");
        return 0;
    }
    if (mode_ == "r") {
        set_debug_msg("CFileBase debug info: File not open for writing.");
        return 0;
    }

    // get file size using 64-bit wrappers
    file_seek64(file_, 0, SEEK_END);
    int64_t file_end = file_tell64(file_);
    
    // If requested position is beyond end, treat as append
    if (pos > file_end) {
        file_seek64(file_, 0, SEEK_END);
        size_t written = write_end(str_content);
        std::ostringstream oss;
        oss << "CFileBase debug info: Appended " << written << " bytes (pos beyond EOF).";
        set_debug_msg_fmt(oss.str());
        return written;
    }

    size_t content_len = std::strlen(str_content);

    if (!is_insert) {
        // OVERWRITE MODE
        int64_t remain = file_end - pos; // bytes available from pos to EOF

        if ((uint64_t)content_len <= (uint64_t)remain) {
            // Fast path: in-place overwrite fits within existing file; no extra allocation needed.
            file_seek64(file_, (int64_t)pos, SEEK_SET);
            size_t bytes_written = std::fwrite(str_content, 1, content_len, file_);
            std::fflush(file_);
            pos_ = tell_pos();
            if (bytes_written != content_len) {
                std::ostringstream oss;
                oss << "CFileBase debug info: Overwrite short write: wrote=" << bytes_written << " expected=" << content_len;
                set_debug_msg_fmt(oss.str());
                return false;
            }
            if (file_content_) {
                std::free((void*)file_content_);
                file_content_ = nullptr;
            }
            set_debug_msg("CFileBase debug info: Overwrite in-place succeeded.");
            return true;
        }

        // Extend overwrite: content_len > remain. We will construct new file image by
        // concatenating prefix [0,pos) and new content, then truncating and writing that
        // buffer back to disk. This uses dynamic memory allocation and requires sufficient
        // system memory (as requested). It avoids writing uninitialized memory and ensures
        // correct final file contents.

        // new_size = pos + content_len
        uint64_t new_size_u64 = (uint64_t)pos + (uint64_t)content_len;
        if (new_size_u64 > (uint64_t)SIZE_MAX - 1) {
            set_debug_msg("CFileBase debug info: New file size too large to allocate in memory.");
            return 0;
        }
        size_t new_size = (size_t)new_size_u64;

        char* new_buf = (char*)std::malloc(new_size + 1);
        if (!new_buf) {
            set_debug_msg("CFileBase debug info: Failed to allocate memory for overwrite extension.");
            return 0;
        }

        // read prefix [0, pos)
        if (pos > 0) {
            file_seek64(file_, 0, SEEK_SET);
            size_t bytes_read_prefix = std::fread(new_buf, 1, (size_t)pos, file_);
            if (bytes_read_prefix != (size_t)pos) {
                std::ostringstream oss;
                oss << "CFileBase debug info: Failed to read prefix for overwrite. read=" << bytes_read_prefix << " expected=" << pos;
                set_debug_msg_fmt(oss.str());
                std::free(new_buf);
                return 0;
            }
        }

        // copy new content into buffer at position pos
        std::memcpy(new_buf + pos, str_content, content_len);
        new_buf[new_size] = '\0';

        // Truncate file to new_size and write buffer
#if defined(_WIN32) || defined(_WIN64)
        // Windows: use _chsize_s on file descriptor
        int fd = _fileno(file_);
        if (fd == -1) {
            set_debug_msg("CFileBase debug info: _fileno failed.");
            std::free(new_buf);
            return 0;
        }
        if (_chsize_s(fd, (long long)new_size) != 0) {
            std::ostringstream oss;
            oss << "CFileBase debug info: _chsize_s failed to truncate to " << new_size;
            set_debug_msg_fmt(oss.str());
            std::free(new_buf);
            return 0;
        }
#else
        int fd = fileno(file_);
        if (fd == -1) {
            set_debug_msg("CFileBase debug info: fileno failed.");
            std::free(new_buf);
            return 0;
        }
        if (ftruncate(fd, (off_t)new_size) != 0) {
            std::ostringstream oss;
            oss << "CFileBase debug info: ftruncate failed to truncate to " << new_size << ": " << std::strerror(errno);
            set_debug_msg_fmt(oss.str());
            std::free(new_buf);
            return 0;
        }
#endif
        // After truncation, write new buffer
        file_seek64(file_, 0, SEEK_SET);
        size_t bytes_written = std::fwrite(new_buf, 1, new_size, file_);
        std::fflush(file_);
        pos_ = tell_pos();
        if (bytes_written != new_size) {
            std::ostringstream oss;
            oss << "CFileBase debug info: Failed to write extended overwrite buffer. wrote=" << bytes_written << " expected=" << new_size;
            set_debug_msg_fmt(oss.str());
            std::free(new_buf);
            return 0;
        }

        if (file_content_) {
            std::free((void*)file_content_);
            file_content_ = nullptr;
        }
        file_content_ = new_buf; // take ownership of buffer representing file contents
        pos_ = pos + content_len; // update position to end of new content
        std::ostringstream oss;
        oss << "CFileBase debug info: Overwrite extended succeeded, new_size=" << new_size << " bytes.";
        set_debug_msg_fmt(oss.str());
        return content_len;
    }
    else {
        // INSERT MODE
        // Save tail (data from pos to EOF) into memory, then write new content, then append the tail back.
        int64_t tail_size = file_end - (int64_t)pos;
        char* tail_buf = nullptr;
        if (tail_size > 0) {
            // 拷贝文件尾部内容（pos之后的内容）到内存中
            if ((uint64_t)tail_size > (uint64_t)SIZE_MAX - 1) {
                set_debug_msg("CFileBase debug info: Tail too large to insert into memory.");
                return 0;
            }
            tail_buf = (char*)std::malloc((size_t)tail_size);
            if (!tail_buf) {
                set_debug_msg("CFileBase debug info: Failed to allocate buffer for tail in insert.");
                return 0;
            }
            file_seek64(file_, (int64_t)pos, SEEK_SET);
            //int64_t pos_inner = tell_pos();
            size_t bytes_read_tail = std::fread(tail_buf, 1, (size_t)tail_size, file_);
            if (bytes_read_tail != (size_t)tail_size) {
                //为什么不相等
                std::ostringstream oss;
                oss << "CFileBase debug info: Failed to read tail for insert. read=" << bytes_read_tail << " expected=" << tail_size;
                set_debug_msg_fmt(oss.str());
                std::free(tail_buf);
                return 0;
            }
        }

        // seek to pos and write new content, then tail
        file_seek64(file_, (int64_t)pos, SEEK_SET);
        size_t bytes_written_main = std::fwrite(str_content, 1, content_len, file_);
        if (bytes_written_main != content_len) {
            std::ostringstream oss;
            oss << "CFileBase debug info: Failed to write main content during insert. wrote=" << bytes_written_main << " expected=" << content_len;
            set_debug_msg_fmt(oss.str());
            if (tail_buf)
                std::free(tail_buf);
            return 0;
        }
        if (tail_buf) {
            size_t bytes_written_tail = std::fwrite(tail_buf, 1, (size_t)tail_size, file_);
            if (bytes_written_tail != (size_t)tail_size) {
                std::ostringstream oss;
                oss << "CFileBase debug info: Failed to write tail during insert. wrote=" << bytes_written_tail << " expected=" << tail_size;
                set_debug_msg_fmt(oss.str());
                std::free(tail_buf);
                return 0;
            }
            std::free(tail_buf);
        }
        std::fflush(file_);
        pos_ = tell_pos();
        {
            std::ostringstream oss2;
            oss2 << "CFileBase debug info: Inserted " << content_len << " bytes at " << pos << ". Tail size=" << tail_size;
            set_debug_msg_fmt(oss2.str());
        }
        if (file_content_) {
            std::free((void*)file_content_);
            file_content_ = nullptr;
        }
        //file_content_ = 
        return content_len;
    }
}

// 中文注释：检查文件是否打开
// 功能：检查文件是否处于打开状态
// 返回值：文件已打开返回 true，否则返回 false
bool CFileBase::is_open() const
{
    return is_open_ && file_ != nullptr;
}

// 判断文件是否是空文件
// 实现说明：
//  - 如果文件当前已经打开，直接使用 fseeko/ftello 获取大小（64-bit）
//  - 如果文件未打开但有 file_name_，尝试以只读方式打开并检查大小
//  - 如果文件无法打开（不存在或权限问题），将其视为"空"（返回 true）并在调试信息中说明原因
// 这是一个设计选择：将不存在的文件视为空文件可以简化调用方逻辑；如果希望区分不存在和空文件，可修改为返回可选状态或额外错误码
bool CFileBase::is_empty() const
{
    // if file is open, use current handle
    if (file_) {
        int64_t current_pos = file_tell64(file_);
        file_seek64(file_, 0, SEEK_END);
        int64_t size = file_tell64(file_);
        file_seek64(file_, current_pos, SEEK_SET); // restore position
        // empty if size == 0
        return size == 0;
    }

    // if we have a filename, try to open to check size
    if (file_name_) {
        FILE* tmp = std::fopen(file_name_, "rb");
        if (!tmp) {
            // cannot open file -> consider empty / not present
            set_debug_msg("CFileBase debug info: File not found or cannot open to determine emptiness.");
            return true;
        }
        file_seek64(tmp, 0, SEEK_END);
        int64_t size = file_tell64(tmp);
        std::fclose(tmp);
        return size == 0;
    }

    // no file handle and no file name -> consider empty
    set_debug_msg("CFileBase debug info: No file handle or file name to check emptiness.");
    return true;
}

// 中文注释：删除指定文件
// 功能：删除指定的文件
// 参数：
//   sz_file_name - 要删除的文件路径，不能为 nullptr
// 返回值：删除成功返回 0，失败返回 -1
char CFileBase::remove_file(const char* sz_file_name)
{
    if (!sz_file_name) {
        set_debug_msg("CFileBase debug info: NULL file name.");
        return -1;
    }
    int remove_result = std::remove(sz_file_name);
    // store errno message for debug
    if (remove_result != 0)
        set_debug_msg(std::strerror(errno));
    else
        set_debug_msg("CFileBase debug info: No error.");
    return (remove_result == 0) ? 0 : -1;
}

// 中文注释：获取调试信息
// 功能：返回类的调试信息字符串
// 返回值：静态调试信息字符串指针
const char* CFileBase::get_debug_mag()
{
    return g_debug_msg.c_str();
}

// Test function: perform a series of exercises to validate the class functionality -- 执行一系列测试以验证该类的功能性
void test_CFileBase() {
    // We'll create a temporary test file in the current working directory
    const char* test_name = "test_cfilebase.txt";
    CFileBase f; // default constructed
    printf("cwd: %s\n", f.get_cwd() ? f.get_cwd() : "(null)");

    // open file for read/write; create if missing
    if (!f.open_file(test_name, "w+")) {
        printf("Failed to open %s\n", test_name);
        return;
    }
    printf("Opened file %s, is_open=%d\n", test_name, f.is_open());

    // write some lines
    f.write_end("Line1\n");
    f.write_end("Line2\n");
    f.write_end("Line3\n");

    // read all content
    f.seek_start();
    std::string all;
    f.read_all(all);
    printf("File content after writes:\n%s\n", all.c_str());

    // overwrite part of file: replace 'Line2' with 'Middle'
    // find position of 'Line2'
    f.seek_start();
    std::string line;
    f.read_line(line); // Line1
    uint64_t pos_after_line1 = f.tell_pos();
    // Now overwrite at this position
    f.write_pos("Middle\n", pos_after_line1, false);
    printf("First debug: %s\n", CFileBase::get_debug_mag());

    // read all
    f.seek_start();
    f.read_all(all);
    printf("After overwrite:\n%s\n", all.c_str());

    // insert something at the end of first line
    f.seek_start();
    f.read_line(line); // read first line
    uint64_t insert_pos = (uint64_t)line.size(); // position after first line read from file pointer is at second line start -- 从文件指针读取第一行后，其位置处于第二行的起始处。
    // actually compute absolute by seeking to start and then moving by number of bytes equal to line size -- 实际上通过查找起始位置然后移动与行大小相等的字节数来计算绝对值
    f.seek_start();
    f.seek_to(insert_pos - 1); // put cursor just before '\n' of first line -- 将光标置于第一行的“\n”符号之前
    f.write_pos("_INSERTED", f.tell_pos(), true);
    printf("Second Debug: %s\n", CFileBase::get_debug_mag());

    f.seek_start();
    f.read_all(all);
    printf("After insert:\n%s\n", all.c_str());
    printf("Third Debug: %s\n", CFileBase::get_debug_mag());

    // test read_size
    f.seek_start();
    std::string part;
    f.read_size(10, part);
    printf("First 10 bytes: '%s'\n", part.c_str());
    printf("Fourth Debug: %s\n", CFileBase::get_debug_mag());

    // close and delete
    f.close_file();
    char rem = CFileBase::remove_file(test_name);
    printf("Removed file %s: %d\n", test_name, rem);
    printf("End Debug: %s\n", CFileBase::get_debug_mag());
}

